package com.svm.operators;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

import libsvm.svm;
import libsvm.svm_model;
import libsvm.svm_node;

import com.svm.bean.Image;
import com.svm.bean.Parameter;
import com.svm.bean.PredicitionResult;
import com.svm.bean.SvmClass;
import com.svm.util.SvmClassUtils;

public class Predicition {

	private svm_node[] node;
	private Image image;
	private Parameter parameter;
	private Double average;

	public Predicition(Image image, Parameter parameter) {
		this.image = image;
		this.parameter = parameter;

	}

	public SvmClass predict() {
		SvmClass svmClass = null;

		try {

			this.loadNode();

			List<SvmClass> classes = SvmClassUtils.listSvmClass();
			List<PredicitionResult> predicition;

			do {

				predicition = this.run(classes);

				classes = new ArrayList<SvmClass>();

				System.out.println("media:" + this.average);

				for (int i = 0; i < predicition.size(); i++) {

					if (predicition.get(i).getPredicitionValue() > this.average) {
						classes.add(predicition.get(i).getSvmClass());
					}
				}

				for (SvmClass s : classes) {
					System.out.println(s.getName());
				}

				this.parameter.setTrainningMode('s');
				this.parameter.setPredicitionMode('s');

				Trainning tr = new Trainning(classes, this.parameter);
				tr.train();

			} while (classes.size() > 1);

			Collections.sort(predicition);

			// DecimalFormat df = new DecimalFormat("#.##");
			// for (PredicitionResult r : predicition) {
			//
			// System.out.println("Class name:" + r.getSvmClass().getName()
			// + " Predicition Value:"
			// + df.format(r.getPredicitionValue()));
			// }

			// Double media = 0.;
			//
			// for (PredicitionResult r : predicition) {
			// System.out.println(r.getSvmClass().getName());
			//
			// for (Image img : r.getSvmClass().getImages()) {
			//
			// EuclidianDistance ed = new EuclidianDistance();
			//
			// media += ed.distance(this.image, img);
			//
			// }
			//
			// media /= r.getSvmClass().getImages().size();
			// System.out.println("media:" + media);
			// System.out.println("***************************");
			// }

			svmClass = predicition.get(predicition.size() - 1).getSvmClass();

			System.out.println(svmClass.getName());

		} catch (IOException ex) {
			System.out.println(ex);
		}

		return svmClass;
	}

	private List<PredicitionResult> run(List<SvmClass> classes)
			throws IOException {

		List<PredicitionResult> predicition = new ArrayList<PredicitionResult>();

		this.average = 0.;

		for (SvmClass sc : classes) {
			String trainningFile;

			switch (parameter.getPredicitionMode()) {
			case 's':
				trainningFile = sc.getSubTrainningFile();
				break;

			default:
				trainningFile = sc.getTrainningFile();
				break;
			}

			svm_model model = svm.svm_load_model(trainningFile);
			Double svmPredict = svm.svm_predict(model, node);
			this.average += svmPredict;
			predicition.add(new PredicitionResult(sc, svmPredict));
		}

		this.average /= classes.size();

		return predicition;
	}

	private void loadNode() throws IOException {

		String line;
		int numeroCaracteristicas;
		StringTokenizer caracteristicas;

		BufferedReader featureVector = new BufferedReader(new FileReader(
				image.getFeatureFilePath()));

		while (featureVector.ready()) {

			line = featureVector.readLine();

			caracteristicas = new StringTokenizer(line, ",");

			numeroCaracteristicas = caracteristicas.countTokens() / 2;

			node = new svm_node[numeroCaracteristicas];

			for (int j = 0; j < numeroCaracteristicas; j++) {
				node[j] = new svm_node();
				node[j].index = Integer.parseInt(caracteristicas.nextToken());
				node[j].value = Double.parseDouble(caracteristicas.nextToken());
			}
		}

		featureVector.close();
	}

}
